package stalker.room;

import stalker.Stalker;
import stalker.room.roomusers.RoomUsers;
import catalog.UniqueNamedStalkerCatalog;
import data.datas.Datas;

/**
 * Mutable class that stores information in a room
 * <p>
 * Factory pattern
 */

public abstract class Room extends Stalker {
  
  private final static UniqueNamedStalkerCatalog catalog_ = new UniqueNamedStalkerCatalog();
  protected final Datas datas_; // mutable
  protected final RoomUsers room_users_; // mutable
  
  private void checkRep() {
    assert (datas_ != null && 
            room_users_ != null  &&
            catalog_ != null) :
      "Room: fields must not be null";
    assert (Stalker.getStalker(this.getID()) == this) :
      "Room: Inconsistent data";
    assert (catalog_.getIDFromName(this.getName()) == this.getID()) :
      "Room: Inconsistend data";
  }
  
  /**
   * Creates a new empty room
   * 
   * @requires name is not null, name is unique
   * @param name Name of this room.
   */
  
  protected Room(String name, Datas datas, RoomUsers room_users) {
    super(name);
    assert datas != null && room_users != null;
    assert (!catalog_.contains(name)) :
      "Name must be unique";
    datas_ = datas;
    room_users_ = room_users;
    catalog_.add(this);
    
    checkRep();
  }
  
  /**
   * Checks if a name is already taken
   * @requires name not null
   * @param name the name that's going to be checked
   * @return true iff name is not taken
   */
  public static boolean isTaken(String name) {
    assert name != null;
    return catalog_.contains(name);
  }
  
  /**
   * @return the datas associated with this room
   */
  public Datas getDatas() {
    return datas_;
  }
  
  /**
   * @return the users associated with this room
   */
  public RoomUsers getRoomUsers() {
    return room_users_;
  }
  
  /**
   * Retrieves a user given its user id
   * @param id user's id, must be present
   * @return User whose id is given
   */
  public static Room getRoomFromID(long id) {
    assert (Stalker.contains(id));
    assert (Stalker.getStalker(id) instanceof Room);
    return (Room)Stalker.getStalker(id);
  }
  
  /**
   * Retrieves a user given its name
   * @param name user's name, must be present
   * @return User whose name is given
   */
  public static Room getRoomFromName(String name) {
    assert (name != null);
    assert (catalog_.contains(name));
    return getRoomFromID(catalog_.getIDFromName(name));
  }
  
}
